#include "netgchannel.h"

#ifdef WIN32
#define usleep(x) Sleep(x)
#endif
#include "socketclient.h"
#include "business_def.h"
#include "Log.h"
#include "datadef.h"
#include "pfunc.h"

NetGChannel::NetGChannel(int gid_)
    : GatherChannel(gid_)
    , running(true)
{
    init(gid_);
};

NetGChannel::~NetGChannel()
{

}

void* NetGChannel::run()
{
    if(NULL==ptr_client)
    {
        CLogger::createInstance()->Log(MsgError,
			"NetGChannel %s(%s,%d) start fail for Socket Client is NULL,[%s %s %d]!"
			, netargs.name.c_str(),netargs.ip.c_str(), netargs.port
			, __FILE__, __FUNCTION__, __LINE__);
        return 0;
    }
    RDClient rdc_data;
    ChannelCmd wdata,rdata;
    unsigned long curTT;
    while (running)
    {
        if(ptr_client->isConnect())
        {
            switch (netargs.type)
            {
            case 1:
            {
				//读取帧数据,进行数据分帧存入缓存
				int ret = ptr_client->Read(rdc_data);
				if (ret > 0)
				{
					cstate.heartTime = static_cast<unsigned int>(time(NULL));
					cstate.m_heart_reconnect_log = false;
					try
					{
						unsigned char * buff = rdc_data.Buf;
						int start_pos = 0;
						unsigned char ctype = 0;
						for (int i = 0; i < rdc_data.len; ++i)
						{
#ifdef DEBUG
							printf_s("%02X ", buff[i]);
#endif
							if (buff[i] > 0xf0)
							{
								if (buff[i] == 0xff)
								{
									if (ctype)
									{
										ctype = 0;
										ChannelCmd rdata_(buff + start_pos, i - start_pos + 1);
                                        ReadDatas->add(rdata_);
										start_pos = i + 1;
									}
								}
								else {
									ctype = buff[i];
									start_pos = i;
								}
							}
						}
#ifdef DEBUG
						printf_s("\n");
#endif
						buff = NULL;
						if (start_pos < rdc_data.len)
						{
							RDClient _newrd(rdc_data.Buf + start_pos, rdc_data.len - start_pos);
							rdc_data = _newrd;
						}
						else {
							rdc_data.len = 0;
						}
					}
					catch (...)
					{
						CLogger::createInstance()->Log(MsgError,
							"NetGChannel(%s) Exception false,[%s %s %d]!"
							, netargs.name.c_str()
							, __FILE__, __FUNCTION__, __LINE__);
					}
				}
            }
                break;
            case 2:
            {
				//读取单帧数据,无分帧,需要时间间隔控制,直接读取,ACSII字段
				char rbuf[256] = { 0 };
				int ret = ptr_client->Read(rbuf, 256);
				if (ret > 0)
				{
					cstate.heartTime = static_cast<unsigned int>(time(NULL));
					cstate.m_heart_reconnect_log = false;
					ChannelCmd rd((unsigned char*)rbuf, ret);
                    ReadDatas->add(rd);
				}
            }
                break;
            default:
                break;
            }

            //数据帧解析,清空队列,即一次下控,一次读取,一次处理          
			while (ReadDatas->pop(rdata))
			{
#ifdef DEBUG
				for (int j = 0; j < rdata.len; j++) 
				{
					printf_s("%02X ", rdata.Buf[j]);
				}
				printf_s("\n");
#endif
				//定义自定义序列化及反序列化
				//未做反序列化及反序列化处理,读取速度要快,防止拼帧
				this->AddFrame(rdata.Buf, rdata.len);
			}
			//
			curTT = static_cast<unsigned long>(clock());
#ifdef __linux__
			curTT = static_cast<unsigned long>(curTT / 1000);
#endif
			if (cmdlist.time_totalcall < curTT && !cmdlist.cmd_totalcall.empty())
			{
				cmdlist.time_totalcall = curTT + protodefs.totalcallsleep;
				if (WriteDatas->size()<3* static_cast<int>(cmdlist.cmd_totalcall.size())) 
				{
					for (std::list<std::string>::iterator it = cmdlist.cmd_totalcall.begin(); it != cmdlist.cmd_totalcall.end(); ++it)
					{
						//char buf[128] = { 0 };
						//int buflen = PFunc::string2bytes((const char*)((*it).c_str()), (unsigned char*)buf, (*it).length());//hex to ascii
						//std::string _cmd = std::string((char*)buf);
						//ChannelCmd wd_cmd((unsigned char*)buf, buflen);
						ChannelCmd wd_cmd((unsigned char*)(*it).c_str(), static_cast<int>((*it).length()));
						WriteDatas->add(wd_cmd);
					}
				}
			}
			
			//下控,每次轮询只执行一条指令
			unsigned char buf_cmd[512] = { 0 };
			int len = this->getBuffer(buf_cmd);
			if (len > 0)
			{
				int wlen = ptr_client->Write((char*)buf_cmd, len);
				if (wlen == len)
				{
					cstate.heartTime = static_cast<unsigned int>(time(NULL));
					cstate.m_heart_reconnect_log = false;
					//
					cstate.newcmd = std::string((char*)wdata.Buf, wdata.len);
					cstate.controlF = wdata.controlF;
					cstate.taskID = wdata.taskID;
					cstate.taskIDUseful = cstate.heartTime+30;
				}
				if (wdata.controlF) 
				{
					CLogger::createInstance()->Log(MsgInfo,
						"TaskID[%lu] and down_node[6] downControl"
						", time(%s), NetGChannel(%s), cmdlen(%d)"
						, wdata.taskID, pyfree::getCurrentTime().c_str()
						, netargs.name.c_str(), wdata.len);
				}
				if (2== netargs.type) 
				{
					usleep(gatheratts.controlSleep*1000);
				}
			}
        }else{
            //for link state is break, then init point value
			if (cstate.m_link_flag) 
			{
				cstate.m_link_flag = false;
				//调整,防止网络不稳点出现重连时,无查询指令设备态势初始化后无法上送当前态势,造成不一致
				if (cstate.linkInitKey) { 
					pointInitReset();
				}
			}
            ptr_client->disConnect();
            bool linkf = ptr_client->connect();
			this->setValue(-1,linkf ? float(1.0) : float(0.0),100089);//更新连接状态
            if(!linkf)
            {
                sleep(15);//连接不上,等待15秒
            }else{
                cstate.m_link_flag = true;
            }
        }
        usleep(1);
    }
    
    return NULL;
}

void NetGChannel::downControl(int _exetype, int _type, int _pid, float _val, unsigned long _taskID)
{
	//printf("etype(%d),type(%d),pid(%d),val(%.2f)\n", _exetype, _type, _pid, _val);
	std::string _cmd = "";
	int checktype = 0;
	unsigned long iplong = 0;
	if (getCmd(_exetype, _type, _pid, _val, _cmd, checktype, iplong, _taskID))
	{
		//for (unsigned int j = 0; j < _cmd.length(); j++) {
		//	printf("%02X", static_cast<unsigned char>(_cmd.at(j)));
		//}
		//printf("\n");
		ChannelCmd _wd((unsigned char*)_cmd.c_str(), static_cast<int>(_cmd.length()),true);
		WriteDatas->add(_wd);
	}
	else {
		CLogger::createInstance()->Log(MsgWarn,
			"TaskID[%lu] and down_node[5-2] GatherChannel(%d,%s) downControl(%d,%d,%d,%.2f) getCmd fail. [%s %s %d]"
			, _taskID, gatheratts.id,gatheratts.name.c_str()
			, _exetype, _type, _pid, _val
			, __FILE__, __FUNCTION__, __LINE__);
	}
}


void NetGChannel::init(int gid_)
{
    running = true;
    // BusinessDef *ptr_BDef = BusinessDef::getInstance();
    if(ptr_BDef->getNetInfoByGID(gid_,netargs))
    {
        ptr_client = new SocketClinet(netargs.ip,netargs.port);
    }
}


int NetGChannel::AddFrame(const unsigned char *buf, int len)
{
	switch (netargs.type)
	{
        case 1:
        {
            //反序列化
            unsigned char * pBuf = new unsigned char[len];
            int nLen = pyfree::uncode(buf, len, pBuf);
            msgResponse(pBuf, nLen);
            delete[] pBuf;
            pBuf = NULL;
        }
        break;
        // case 2://单帧,ascii
        // {
        //     msgResponse((unsigned char *)buf, len);
        // }
        // break;
        default:
		{
            msgResponse((unsigned char *)buf, len);
        }
		break;
	}
	return 1;
}

void NetGChannel::msgResponse(unsigned char *buf, int len, unsigned long dev_addr)
{
	char _buf[512] = { 0 };
#ifdef DEBUG
	printf("msgResponse len(%d) from(%lu):\n", len,dev_addr);
	for (int i = 0; i < len; i++)
	{
		printf("%02X", buf[i]);
	}
	printf("\n");
#endif
	int rlen = pyfree::bytes2string(buf, _buf, len);//ascii to hex
	std::string atres = std::string((char*)_buf);
	std::string _otherDesc = "";
	rlen+=1;
	if(protodefs.oldState>0)//脚本解析需要下发指令
	{
		char d_buf[512] = { 0 };
		int dlen = pyfree::bytes2string((unsigned char *)cstate.newcmd.c_str()
			, d_buf, static_cast<int>(cstate.newcmd.length()));//control cmd,ascii to hex
		_otherDesc = std::string((char*)d_buf, dlen);
	}
	unsigned long _taskID = cstate.taskID;
	if (_taskID <= 0) 
	{
		_taskID = pyfree::getTaskIDFromDateTime(0);//无下控任务ID,创建新编号
	}
	msgAnalysis(atres,_otherDesc,_taskID,false,dev_addr);
	setValue(-3,1.0,_taskID,dev_addr);	//信道读取数据正常
}

int NetGChannel::getBuffer(unsigned char* _buf)
{
	ChannelCmd it;
	if(!WriteDatas->pop(it)){
		return 0;
	}
	// printf("getBuffer:\n");
	// for (int j = 0; j < it.len; j++) {
	// 	printf("%02X", static_cast<unsigned char>(it.Buf[j]));
	// }
	// printf("\n");
	int nlen = 0;
	switch (netargs.type)
	{
		case 1:
		{
			nlen = pyfree::code((unsigned char*)it.Buf, it.len, _buf);
		}
		break;
		// case 2:
		// {
		// 	memcpy(_buf,it.Buf,it.len);
		// 	nlen = it.len;
		// }
		// break;
		default:
		{
			memcpy(_buf,it.Buf,it.len);
			nlen = it.len;
		}
		break;
	}
	return nlen;
}